package controller

import (
	"context"

	"fmt"
	"gin_miaosa/zhiliao_seckill_srv/data_source"
	"gin_miaosa/zhiliao_seckill_srv/models"
	"gin_miaosa/zhiliao_seckill_srv/redis_lib"
	zhiliao_seckill_srv "gin_miaosa/zhiliao_seckill_srv/seckill_proto/seckill_seckill"
	"gin_miaosa/zhiliao_seckill_srv/utils"

	// "gin_miaosa/zhiliao_seckill_srv/redis_lib"
	// "gin_miaosa/zhiliao_seckill_srv/utils"
	// "github.com/streadway/amqp"
	"time"

	"github.com/streadway/amqp"
)

type SecKill struct {

}

func (s *SecKill)FrontSecKill(ctx context.Context, in *zhiliao_seckill_srv.SecKillRequest, out *zhiliao_seckill_srv.SecKillResponse) error  {
	id := in.Id
	/*
	秒杀逻辑：
		减库存

	限制：
		1.开始时间：还没有开始就不能购买，
			能正常购买的情况：
				当前时间 >= start_time
		2.结束时间：
			能正常购买的情况：
				当前时间 < 结束时间
		3.数量：活动的数量如果为0就能下单

		4.每个用户只能购买一个：依赖于“订单”
	 */
	 seckill := models.SecKills{}
	 now_time := time.Now()
	 result := data_source.Db.Where("id = ?",id).Find(&seckill)

	 if result.Error != nil {
		 out.Code = 500
		 out.Msg = "下单失败，请重试"
		 return nil
	 }
	 fmt.Println("=======FrontSecKill========",id,"time",now_time,"user",in.FrontUserEmail)
	 // 当前时间 >= 开始时间 可以正常抢购
	// 如果查询到数据了，不会报错,能正常下单
	// 如果没有查询到数据，会报错，但是不能正常下单
	 ret_start_time := result.Where("start_time <= ?",now_time).Find(&seckill)

	 if ret_start_time.Error != nil{
	 	out.Code = 500
	 	out.Msg = "抢购还未开始"
		 fmt.Println("#########抢购还未开始########")
		 return nil
	 }

	 // 当前时间 < 结束时间   可以正常抢购

	ret_end_time := ret_start_time.Where("end_time > ?",now_time).Find(&seckill)

	if ret_end_time.Error != nil {
		out.Code = 500
		out.Msg = "抢购已经结束"
		 fmt.Println("#########抢购已经结束########")
		 return nil
	}

	// 活动库存必须大于0    可以正常抢购
	ret_num := result.Where("num > 0").Find(&seckill)
	if ret_num.Error != nil {
		out.Code = 500
		out.Msg = "你来晚了，已抢完"
		 fmt.Println("#########你来晚了，已抢完########")
		 return nil
	}
	// 获取用户信息
	front_user_email := in.FrontUserEmail


	// 每个用户只能购买一个  购买数量<1  可以正常抢购
	order_rep := models.Orders{}
	ret_uemail := data_source.Db.Where("uemail = ?",front_user_email).Where("sid = ?",id).Find(&order_rep)

	// 如果查询到数据了，不会报错，但是不能正常下单
	// 如果没有查询到数据，会报错，但是能正常下单
	if ret_uemail.Error == nil {
		out.Code = 500
		out.Msg = "下单失败，每个用户只能购买一次"
		 fmt.Println("#########下单失败，每个用户只能购买一次########")
		 return nil

	}
	// 正常的
	ret := result.Update("num",seckill.Num-1)

	// 生成订单：购买成功才往订单表中插入数据

	order := models.Orders{
		Uemail:front_user_email,
		Sid:int(id),
		CreateTime:time.Now(),
	}
	ret_order := data_source.Db.Create(&order)

	if ret_order.Error != nil {
		out.Code = 500
		out.Msg = "下单失败，请重试"
		return nil

	}

	if ret.Error != nil {
		out.Code = 500
		out.Msg = "下单失败，请重试"
		return nil
	}
	fmt.Println("#########下单成功########")

	out.Code = 200
	out.Msg = "下单成功"
	return nil

}

// 从队列中读取任务并消费
func init()  {

	go func() {
		conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
		// conn, err := amqp.Dial("amqp://admin:admin@192.168.0.105:5672//myvhost")
		fmt.Println(err)
		defer conn.Close()
		ch,err_ch := conn.Channel()
		fmt.Println(err_ch)
		defer ch.Close()

		ch.Qos(1,0,false)


		deliveries,err := ch.Consume("zhiliao_web.order_queue","order_consumer",false,false,false,false,nil)
		//deliveries,err := ch.Consume("first_queue","first_consumer",false,false,false,false,nil)
		if err != nil {
			fmt.Println(err)
		}

		for delivery := range deliveries {
			//fmt.Println(delivery.ContentType)
			//fmt.Println(string(delivery.Body))
			//delivery.Ack(true)
			go Orderapply(delivery)
		}
	}()

}


func Orderverify(delivery amqp.Delivery,id interface{},front_user_email string)bool{
	
	seckill := models.SecKills{}
	now_time := time.Now()
	result := data_source.Db.Where("id = ?",id).Find(&seckill)
	uniqueKey := fmt.Sprintf("%s:%s", front_user_email, id)
	if result.Error != nil {
		map_data := map[string]interface{}{
			"code" : 500,
			"msg" : "找不到该商品！！",
		}
		redis_lib.Conn.Do("SET",uniqueKey,utils.MapToStr(map_data))
		fmt.Println("SET",uniqueKey,utils.MapToStr(map_data))
		return false
	}
	// 当前时间 >= 开始时间 可以正常抢购
	// 如果查询到数据了，不会报错,能正常下单
	// 如果没有查询到数据，会报错，但是不能正常下单
	ret_start_time := result.Where("start_time <= ?",now_time).Find(&seckill)

	if ret_start_time.Error != nil{
		map_data := map[string]interface{}{
			"code" : 500,
			"msg" : "抢购还未开始",
		}
		redis_lib.Conn.Do("SET",uniqueKey,utils.MapToStr(map_data))
		fmt.Println("SET",uniqueKey,utils.MapToStr(map_data))
		return false
	}

	// 当前时间 < 结束时间   可以正常抢购

	ret_end_time := ret_start_time.Where("end_time > ?",now_time).Find(&seckill)

	if ret_end_time.Error != nil {
		map_data := map[string]interface{}{
			"code" : 500,
			"msg" : "抢购已经结束",
		}
		redis_lib.Conn.Do("SET",uniqueKey,utils.MapToStr(map_data))
		fmt.Println("SET",uniqueKey,utils.MapToStr(map_data))
		return false
	}
	// 活动库存必须大于0    可以正常抢购
	ret_num := result.Where("num > 0").Find(&seckill)
	if ret_num.Error != nil {
		map_data := map[string]interface{}{
			"code" : 500,
			"msg" : "你来晚了，已抢完",
		}
		redis_lib.Conn.Do("SET",uniqueKey,utils.MapToStr(map_data))
		fmt.Println("SET",uniqueKey,utils.MapToStr(map_data))
		return false
	}
	// 每个用户只能购买一个  购买数量<1  可以正常抢购
	order_rep := models.Orders{}
	ret_uemail := data_source.Db.Where("uemail = ?",front_user_email).Where("sid = ?",id).Find(&order_rep)

	// 如果查询到数据了，不会报错，但是不能正常下单
	// 如果没有查询到数据，会报错，但是能正常下单
	if ret_uemail.Error == nil {
		map_data := map[string]interface{}{
			"code" : 500,
			"msg" : "下单失败，每个用户只能购买一次",
		}
		redis_lib.Conn.Do("SET",uniqueKey,utils.MapToStr(map_data))
		fmt.Println("SET",uniqueKey,utils.MapToStr(map_data))
		return false
	}
	ret := result.Update("num",seckill.Num-1)
	// 生成订单：购买成功才往订单表中插入数据
	order := models.Orders{
		Uemail:front_user_email,
		Sid:utils.StrToInt(id.(string)),
		CreateTime:time.Now(),
	}
	ret_order := data_source.Db.Create(&order)

	if ret_order.Error != nil {
		map_data := map[string]interface{}{
			"code" : 500,
			"msg" : "下单失败，请重试",
		}
		redis_lib.Conn.Do("SET",uniqueKey,utils.MapToStr(map_data))
		fmt.Println("SET",uniqueKey,utils.MapToStr(map_data))
		return false

	}
	if ret.Error != nil {
		map_data := map[string]interface{}{
			"code" : 500,
			"msg" : "下单失败，请重试",
		}
		redis_lib.Conn.Do("SET",uniqueKey,utils.MapToStr(map_data))
		fmt.Println("SET",uniqueKey,utils.MapToStr(map_data))
		return false
	}
	return true
}


// mhysql中的前端重复提交判断
// order_mq := models.Orders{}
// var count_mq int
// data_source.Db.Where("uemail = ?",front_user_email).Find(&order_mq).Count(&count_mq)
// if count_mq > 0 {
// 	delivery.Ack(true)
// 	fmt.Println("前端重复提交",count_mq)
// 	return
// }


func Orderapply(delivery amqp.Delivery)  {
	body := string(delivery.Body)
	fmt.Println(body)
	
	request_data := utils.StrToMap(body)
	
	id := request_data["pid"]
	front_user_email := request_data["uemail"].(string)
	fmt.Println("=====Orderapply=======",id,front_user_email)

	uniqueKey := fmt.Sprintf("%s:%s", front_user_email, id)
	if !Orderverify(delivery,id ,front_user_email ){
		// 如果订单没成功 
		delivery.Ack(true)
		return
	}
	// 成功的
	delivery.Ack(true)
	map_data := map[string]interface{}{
		"code" : 200,
		"msg" : "下单成功 未付款！！ （请在1分钟内付款）",
	}
	redis_lib.Conn.Do("SET",uniqueKey,utils.MapToStr(map_data))
	fmt.Println("###下单成功##redis set",uniqueKey,":",utils.MapToStr(map_data))
	return
}


func (s *SecKill)Pay(ctx context.Context, in *zhiliao_seckill_srv.PayRequest, out *zhiliao_seckill_srv.PayResponse) error  {
	 id := in.Id
	 front_user_email := in.FrontUserEmail
	 uniqueKey := fmt.Sprintf("%s:%d", front_user_email, id)
	//  z找可能订单不存在
	// 每个用户只能购买一个  购买数量<1  可以正常抢购
	order_rep := models.Orders{}

	result := data_source.Db.Where("uemail = ?",front_user_email).Where("sid = ?",id).Find(&order_rep)
	// 如果查询到数据了，不会报错，但是不能正常下单
	// 如果没有查询到数据，会报错，但是能正常下单
	if result.Error != nil {
		out.Code = 500
		out.Msg = "付款失败，订单不存在"
		fmt.Println("#########付款失败，订单不存在########")
		return nil
	}
	// 如果数据库状态为-1 超时 没付款  并且把结果的redis状态设置为付款失败
	status_ret := result.Where("status = -1").Find(&order_rep)
	if status_ret.Error == nil{
		out.Code = 500
		out.Msg = "付款超时请重新下单"
		fmt.Println("#########付款超时请重新下单########")

		map_data := map[string]interface{}{
			"code" : 500,
			"msg" : "付款超时请重新下单！！",
		}
		
		redis_lib.Conn.Do("SET",uniqueKey,utils.MapToStr(map_data))
		fmt.Println("SET",uniqueKey,utils.MapToStr(map_data))
		return nil
	}

	// 如果为1则重复付款
	status_ret = result.Where("status = 1").Find(&order_rep)
	if status_ret.Error == nil{
		out.Code = 500
		out.Msg = "重复付款"
		fmt.Println("#########重复付款########")

		map_data := map[string]interface{}{
			"code" : 500,
			"msg" : "重复付款！！",
		}
		
		redis_lib.Conn.Do("SET",uniqueKey,utils.MapToStr(map_data))
		fmt.Println("SET",uniqueKey,utils.MapToStr(map_data))
		return nil
	}
	// 如果为0 成功付款
	status_ret = result.Where("status = 0").Find(&order_rep)
	if status_ret.Error == nil{
		out.Code = 200
		out.Msg = "付款成功"
		fmt.Println("#########付款成功########")

		map_data := map[string]interface{}{
			"code" : 500,
			"msg" : "付款成功！！",
		}
		ret:=result.Update("status",1)
		fmt.Println("ret",ret)
		redis_lib.Conn.Do("SET",uniqueKey,utils.MapToStr(map_data))
		fmt.Println("SET",uniqueKey,utils.MapToStr(map_data))
		return nil
	}
	out.Code = 500
	out.Msg = "未知错误"
	return nil

}


